package yxy.game.pm2.module.shop.handle;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import org.joda.time.DateTime;

import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.model.DataClass;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.PackageMessage;
import yxy.game.pm2.message.ShopMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.shop.Goods;
import yxy.game.pm2.module.shop.GoodsLimitType;
import yxy.game.pm2.module.shop.ShopModule;

abstract public class ShopHandle<D extends DataClass> {
	public static int BUY_MIN_NUM = 0;
	public static int BUY_MAX_NUM = 99; //单次最大可购买数量，防止外挂输入int大数导致溢出。

	public static void checkBuyNumber (int num) throws Exception {
		if (num < BUY_MIN_NUM || num > BUY_MAX_NUM) throw new Exception("num error : " + num);
	}

	/** 获取所有商品 */
	public Collection<ShopMessage.Goods> goods(String playerCode) {
		ShopModule module = getModule(playerCode);
		ArrayList<ShopMessage.Goods> goodsmessage = new ArrayList<>();
		for (Goods goods : module.getGoods()) {
			try {
				goodsmessage.add(packGoods(goods));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return goodsmessage;
	}

	/** 封装单个商品 */
	public ShopMessage.Goods packGoods(Goods goods) {
		D data = data(goods.getDataId());
		CurrencyHandle currencyHandle = new CurrencyHandle();

		ShopMessage.Goods.Builder builder = ShopMessage.Goods.newBuilder();
		builder.setId(goods.getId());
		builder.setSell(goods.getSell());
		builder.setSellout(goods.sellout(limit(data)));
		builder.setLimit(limit(data));
		builder.setLimitype(limitType(data).getNumber());
		builder.setCost(currencyHandle.packItem(cost(data, 1)));
		builder.setPurchase(currencyHandle.packItem(purchase(data, 1)));
		builder.setRebate(rebate(data));
		builder.setParam(param(data));
		return builder.build();
	}

	/** 购买 */
	public Result buy(String playerCode, int id, int num, BuyResponse response) {
		ShopModule module = getModule(playerCode);
		for (Goods goods : module.getGoods()) {
			if (goods.getId() == id) {
				D data = data(goods.getDataId());
				GoodsLimitType limittype = limitType(data);
				if (!limittype.equals(GoodsLimitType.不限购)) {
					int limit = limit(data);
					if (goods.sellout(limit)) {
						return Result.ShopSellOut;// 商品已经卖光
					}
					if (limit > 0 && num + goods.getSell() > limit) {
						return Result.ShopSellLimitOut;// 购买数量超出限购
					}
				}
				Currency cost = cost(data, num);
				try {
					new CurrencyHandle().cost(playerCode, CCReason.商店, cost);
				} catch (CurrencyNotEnoughException e) {
					return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 消费不足
				}
				Currency purchase = purchase(data, num);

				new CurrencyHandle().addCurrency(playerCode, CCReason.商店, purchase);

				goods.setSell(goods.getSell() + num);
				module.set();

				// 封装消息
				response.setPurchase(new CurrencyHandle().packItem(purchase));
				response.setGoods(packGoods(goods));

				return Result.Success;
			}
		}
		return Result.ParamError;
	}

	public boolean update(Goods goods, DateTime now) {
		D data = data(goods.getDataId());
		return goods.update(now, limitType(data));
	}

	// abstract===========================================================================

	abstract public ShopModule getModule(String playerCode);

	/** 限购类型 */
	abstract public GoodsLimitType limitType(D data);

	/** 限购数量 */
	abstract public int limit(D data);

	/** 折扣 */
	abstract public int rebate(D data);

	/** 消费 */
	abstract public Currency cost(D data, int num);

	/** 购买 */
	abstract public Currency purchase(D data, int num);

	/** 附加参数 */
	public int param(D data) {
		return 0;
	}

	abstract public Class<D> clazz();

	public Map<String, D> datas() {
		if (datas == null) {
			datas = DataCenter.getAllData(clazz());
		}
		return datas;
	}

	public D data(int id) {
		return datas().get(String.valueOf(id));
	}

	private Map<String, D> datas;

	static public class BuyResponse {
		private PackageMessage.Item purchase;
		private ShopMessage.Goods goods;

		public PackageMessage.Item getPurchase() {
			return purchase;
		}

		public void setPurchase(PackageMessage.Item purchase) {
			this.purchase = purchase;
		}

		public ShopMessage.Goods getGoods() {
			return goods;
		}

		public void setGoods(ShopMessage.Goods goods) {
			this.goods = goods;
		}

	}

	public static void checkTip(String playerCode) {
		// 市集
		new MerchantHandle().getModule(playerCode);
	}
}
